/*
 * Project: Remote Access Control (RAC)
 * File: rac-server.c
 * Version: v5.5.10
 * Copyright (c) 2008-2009
 * Author: Jonathan Salwan
 * Mail: js.rac.projet@gmail.com  
 * All rights reserved.
 *
 * English:
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *
 * French:
 * La redistribution et l'utilisation sous forme source et binaire, 
 * avec ou sans modification, sont autorisées à condition que les 
 * conditions suivantes soient remplies:
 * 1. Les redistributions du code source doivent contenir la notice 
 *    de copyright ci-dessus, cette liste de conditions et la clause 
 *    de non responsabilité.
 * 2. Les redistributions sous forme binaire doivent reproduire la 
 *    notice de copyright ci-dessus, cette liste de conditions et la 
 *    clause de non responsabilité dans la documentation et / ou d'autres 
 *    documents fournis avec la distribution.
 *
 */


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <openssl/md5.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include "log.h"
#include "info.h"

void root()
{
	fprintf(stderr,"\nErreur: Vous devez être root pour lancer le Server RAC\n\n");
	exit(0);
}


int main(int argc, char *argv[])
{

	if(geteuid() == 0)
	{
	FILE *port, *port_write, *Fichier, *fp2;
	
	//droit access
	        char id[16];
        	Fichier = fopen(id_file, "r" );
        	fgets( id, sizeof(id), Fichier);
		
			//uid()=racuser
			int test = setuid(atoi(id));
			
				if( test == -1)
				      {
				      fprintf(stderr,"Erreur Id\n");
				      return 0;
				      }
			

	int mysocket;
	int mysocket2;
	int srv_accept;
	int sockaddr_long;
	int client_len;
	
	//Verification existance fichier port.conf
	
        	if(port = fopen(port_file,"r") == NULL)
        		{
			port_write = fopen(port_file,"w"); 
			fprintf(port_write, port_default); //port par default 
			fclose(port_write);
        		}

        char portconf[16];
        	Fichier = fopen(port_file, "r" );
        	fgets( portconf, sizeof(portconf), Fichier);


	int prt = atoi(portconf);

	struct sockaddr_in sockaddr_mysocket;
	struct sockaddr_in client_address;
	struct sockaddr_in *ip;

        	sockaddr_long = sizeof(sockaddr_mysocket);
		sockaddr_mysocket.sin_family = AF_INET;
		sockaddr_mysocket.sin_addr.s_addr = htonl(INADDR_ANY);
		sockaddr_mysocket.sin_port = htons(prt);
		
		


	//enregistre la version du server
	fp2 = fopen(service_file,"w");
	fprintf(fp2, version_server);
	fclose(fp2);

        fprintf(stdout,"\n----------------------------------------\n");
        fprintf(stdout,"             Server Activé        \n");
        fprintf(stdout,"----------------------------------------\n");


        mysocket2 = socket(PF_INET, SOCK_STREAM, 0);
        	if(mysocket2 == -1)
		{
        	perror("");
		exit(0);
		}


while(1)
{	
	bind(mysocket2, (struct sockaddr*)&sockaddr_mysocket, sockaddr_long);
	listen(mysocket2, 2);

		client_len = sizeof(client_address);
		srv_accept = accept(mysocket2, (struct sockaddr*)&client_address,&client_len);
		
			ip = (struct sockaddr_in *)&client_address;

			printf("[+]Connexion reçus ip: %s\n", inet_ntoa(ip->sin_addr));
			log(log_con_recu, inet_ntoa(ip->sin_addr));

			char login[] = "\nRemote Access Control (RAC) 2009-2010\n"
				       "Version: v5.5.10\n\n"
				       "[+]Connected\n"
				       "[+]Password : ";
		
			send(srv_accept,login,sizeof(login),0);
			
			char reponse[512];
			memset(reponse,0,512);
			
				fprintf(stdout,"[+]Attente reponse\n");
				recv(srv_accept, reponse, sizeof(reponse), 0);

					fprintf(stdout,"[+]Password reçus\n");
					fprintf(stdout,"[+]Verification ip...\n");

			char verif_ip[512];
			sprintf(verif_ip, "grep -w %s /etc/rac/auth/ip.conf", inet_ntoa(ip->sin_addr));

			if(system(verif_ip) != NULL)
                		{
                		fprintf(stdout,"[+]IP valide\n");
				log(log_ip_true, inet_ntoa(ip->sin_addr));
				fprintf(stdout,"[+]Verification Password...\n");


////////////////////////////////////////////////////////////////////////////////////////////////////////////
                char *Password = reponse;
                        char pwdmd5[33];

                        int i;

                        FILE                    *fichier_md5,
                                                *fichier_md5_read;

                        fichier_md5             = fopen("/tmp/pwd_rac", "w");
                        fichier_md5_read        = fopen("/tmp/pwd_rac", "r");

                                unsigned char md[MD5_DIGEST_LENGTH];
                                MD5(Password, strlen(Password)-1,md);

                                for(i=0;i<MD5_DIGEST_LENGTH;i++)
                                fprintf(fichier_md5, "%02x",md[i]);
                        fclose(fichier_md5);

			char pwd_client[33];
			fgets( pwd_client, sizeof(pwd_client), fichier_md5_read);

			printf("[+]Hash: %s\n",pwd_client);

					char pwd_recv[33];
        				FILE *password;

                				password = fopen(pwd_file, "r");
                                		fgets( pwd_recv, sizeof(pwd_recv), password);
					
					//ajout de line feed sur pwd
					char pwd_line_feed[34];
					sprintf(pwd_line_feed,"%s\n",pwd_client);

////////////////////////////////////////////////////////////////////////////////////////////////////////////
			
			if(!strcmp(pwd_recv, pwd_client) || !strcmp(pwd_line_feed, pwd_client)) 
				{
				fprintf(stdout,"[+]Password valide\n");
				log(log_pwd_true, inet_ntoa(ip->sin_addr));
				char correct[] = "[+]Password Accept\n\n";
					send(srv_accept,correct,sizeof(correct),0);								
					int ret;
					int access = 1;
					//chroot l'utilisateur
					chdir(CHROOT);
					char cmd_recu[512];

			//send the first head	
			char head[] = "@:> ";
					
			while(access == 1)
				{

				send(srv_accept,head,sizeof(head),0);                                

                                memset(cmd_recu,0,512);
                                recv(srv_accept,cmd_recu,sizeof(cmd_recu),0);

					//Verifi si le client a envoyé "disconnect" si oui 
					//le serveur coupe le socket
					//sinon il execute la commande
					if(!strcmp(cmd_recu, "exit") || !strcmp(cmd_recu, "exit\n"))
						{		
							fprintf(stdout,"[+]Client Disconnect\n");
							char quit[] = "[+]Disconnect\n";
							send(srv_accept,quit,sizeof(quit),0);
							shutdown(mysocket2,1);
							log(log_disconnect, inet_ntoa(ip->sin_addr));
							access = 0;
						}		
						else
						{
							dup2(srv_accept,fileno(stdout));
							dup2(srv_accept,fileno(stdin));
							dup2(srv_accept,fileno(stderr));
							system(cmd_recu);
							log(cmd_recu, inet_ntoa(ip->sin_addr));
						}
				
				}//boucle while
				
			}
			//Sinon le password est invalide
			//Donc affirme que le code est faux au client  
			else
			{
				fprintf(stdout,"[+]Password invalide\n");
				char failed[] = "[+]Password failed";
				log(log_pwd_false, inet_ntoa(ip->sin_addr));
				send(srv_accept,failed,sizeof(failed),0);
				
				shutdown(mysocket2,1);
			}
                                
			}//section ip verification
			//Sinon l'ip est interdite
			else{
                                fprintf(stderr,"[+]IP interdite\n");
                                fprintf(stdout,"[+]Client Disconnect\n");
				char failed[] = "IP interdite";
                                	
					log(log_ip_false, inet_ntoa(ip->sin_addr));
                                	send(srv_accept,failed,sizeof(failed),0);

                               	shutdown(mysocket2,1);
                                }


}//boucle while principale

}//if uid == 0 

	else
	{
		root();
		exit(0);
	}

}
